#include "SRTFscheduler.h"


SRTFscheduler::SRTFscheduler()
{

}

SRTFscheduler::~SRTFscheduler()
{
}



SRTFscheduler::SRTFscheduler(map<string, Worker>* workers,Mailer* mailer)
//	m_curThreadPhase(0),m_contex_switch_count(0),m_quanta_count(0),m_msg_passed_count(0),m_phase_count(0)
{
//	m_curThreadPhase = 0;
	//m_tT = &tT;
	m_workers = workers;
	m_mailer = mailer;
	init();
}

/* we will initialize 2 queues for the RRschduler - one of blocked threads(table) queue
 * and the other - active threads queue
 */
void SRTFscheduler::init(){


	map<string, Worker>::iterator iter;
	//threadsTable* tTable = (threadsTable*)getThreadsTable();
	map<string, Worker>* workers = m_mailer->getWorkers();


	  for(iter = m_mailer->getWorkers()->begin(); iter != m_mailer->getWorkers()->end() ; iter++){
		  if( iter->second.isMailBoxEmpty()){          /* iter->second == worker */
		  			//((m_tT->find((iter->second).getMyID()))->second).status = "blocked";
		  			m_blocked_threads.push(&(iter->second));
		  		}
		  		else if (m_mailer->isFull() && (iter->second.getQuanta() > 0)){
		  		//	((m_tT->find((iter->second).getMyID()))->second).status = "blocked";
		  			m_blocked_threads.push(&(iter->second));
		  		}else{
		  			//((m_tT->find((iter->second).getMyID()))->second).status = "active";
		  			m_active_threads.push(&(iter->second));}


	  }
////////////////////////////////////////////////////////////////////////////////
			  ////////////////////		  ////////////////////////////////////////
/*	for(iter = workers->begin() ; iter != workers->end() ;++iter){


		if( iter->second.isMailBoxEmpty()){           iter->second == worker
			((m_tT->find((iter->second).getMyID()))->second).status = "blocked";
			m_blocked_threads.push(&(iter->second));
		}
		else if (m_mailer->isFull() && (iter->second.getQuanta() > 0)){
			((m_tT->find((iter->second).getMyID()))->second).status = "blocked";
			m_blocked_threads.push(&(iter->second));
		}else
			((m_tT->find((iter->second).getMyID()))->second).status = "active";
			m_active_threads.push(&(iter->second));



	}*/



}




void SRTFscheduler::nextWorker(){

		/*  check for blocked threads that are ready to work again */
		for (unsigned int i=0;i < m_blocked_threads.size() ;i++) {

			Worker* worker = m_blocked_threads.top();
			m_blocked_threads.pop();
			if (worker->isMailBoxEmpty()) {
				//((m_tT->find(worker->getMyID()))->second).status = "blocked";
				m_blocked_threads.push(worker);
			}
			else if (!(m_mailer->isFull()) && (worker->getQuanta() != 0)) {
				//((m_tT->find(worker->getMyID()))->second).status = "blocked";
				m_blocked_threads.push(worker);
			}
			else {
				//((m_tT->find(worker->getMyID()))->second).status = "active";
				m_active_threads.push(worker);
			}
		}


		/*  check for active threads that aren't doing anything */
		for (unsigned int i=0 ;i < m_active_threads.size();i++) {

			Worker* worker = m_active_threads.top();
			m_active_threads.pop();
			if (worker->isMailBoxEmpty()) {
				m_blocked_threads.push(worker);
			}
			else if (!(m_mailer->isFull()) && (worker->getQuanta() != 0)) {
				m_blocked_threads.push(worker);
			}
			else {
				m_active_threads.push(worker);
			}
		}


		/*give the next worker quanta */

		if (m_active_threads.size() != 0) {

			Worker* worker = m_active_threads.top();
			//notifyThreadChange(worker);
			incCScount();

			m_active_threads.pop();

			int new_quanta = worker->getNeededQuanta();
			worker->setQuanta(new_quanta);
			incQuantaCount();
			incMsgPass();
			m_active_threads.push(worker);


		}
		cout<<"next worker ...." << endl;

}


/* increment the contex switches count by 1 */
void SRTFscheduler::incCScount(){
	m_contex_switch_count++;
}

void SRTFscheduler::incMsgPass(){
	m_msg_passed_count++;
}

void SRTFscheduler::incQuantaCount(){
	m_quanta_count++;
}

bool SRTFscheduler::isStable(){

	int current_phases = 0;

	map<string, Worker>::iterator iter;
	map<string, Worker>* workers = m_workers;
	for(iter = workers->begin() ; iter != workers->end() ;++iter){
		current_phases =+ iter->second.getPhase() ;
	}

	if ((m_phase_count == current_phases) & (current_phases != 0)) {
			return true;
	}

	m_phase_count = current_phases;
	return false;

}

/* prints summary :
	 *
	 * - number of context switches between threads.
	 * - sum of message quanta given to all worker threads from last initialization.
	 * - actual number of messages passed from last initialization.
	 * - the thread table .
	 */
void SRTFscheduler::printSum(){
	cout << " SUMMARY of scheduling iteration : \n" ;
	cout << " - number of context switches :\t" << m_contex_switch_count <<"\n";
	cout << " - message quanta given :\t" << m_quanta_count <<"\n";
	cout << " - message passed  :\t" << m_msg_passed_count <<"\n";
	cout << " - thread tables : \n";
	cout << "\t ID \t\t STATUS \t\t MSG_DELIVERED \t\t MSG_TOTAL \t\t PRIORITY \n ";
/*	threadsTable::iterator iter;
	for(iter = m_tT->begin() ; iter != m_tT->end() ;++iter){
		cout << "\t " << iter->first ;
		cout << "\t\t " << iter->second.status;
		cout << "\t\t " << iter->second.accuMessQua;
		cout << "\t\t\t " << iter->second.totMessQua;
		cout << iter->second.priority << " \n" ;
	}*/
}





